/**
 * 读取文件，并提供进度回调
 * @param {Object} options - 配置选项
 * @param {File|Blob} options.blob - 输入文件或Blob对象
 * @param [{(progress: number, loaded: number, total: number) => void}] options.onProgress - 进度回调函数
 * @returns {Promise<ArrayBuffer>} 文件数据
 */
export async function readBlobAsArrayBuffer(options: {
    blob: File | Blob;
    onProgress?: (progress: number, loaded: number, total: number) => void;
}): Promise<ArrayBuffer> {
    const { blob, onProgress } = options;
    const blobSize = blob.size;
    const result = new Uint8Array(blobSize);

    return processBlobChunks({
        blob,
        onChunk: async (chunkArrayBuffer: ArrayBuffer, offset) => {
            const chunkArray = new Uint8Array(chunkArrayBuffer);
            result.set(chunkArray, offset);

            // 调用进度回调
            if (onProgress) {
                const loaded = offset + chunkArray.length;
                const progress = (loaded / blobSize) * 100;
                onProgress(progress, loaded, blobSize);
            }
        }
    }).then(() => result.buffer)
        .catch((error) => {
            throw new Error(`文件读取错误：${error.message || '未知错误'}`);
        });
}

/**
 * 分块处理Blob数据的通用函数
 * @param {Object} options - 配置选项
 * @param {Blob} options.blob - 要处理的Blob对象
 * @param {number} [options.chunkSize=1024*1024] - 分块大小(字节)，默认1MB
 * @param {(chunk: ArrayBuffer, offset: number) => Promise<void>} options.onChunk - 处理每个块的回调函数
 * @param {(progress: number) => void} [options.onProgress] - 进度回调函数，参数为当前进度(0-100)
 * @returns {Promise<void>} 处理完成的Promise
 */
export async function processBlobChunks(options: {
    blob: Blob;
    chunkSize?: number;
    onChunk: (chunk: ArrayBuffer, offset: number) => Promise<void>;
    onProgress?: (progress: number) => void;
}): Promise<void> {
    const { blob, chunkSize = 1024 * 1024, onChunk, onProgress } = options;
    const blobSize = blob.size;
    let offset = 0;

    async function readNextChunk(): Promise<void> {
        if (offset >= blobSize) {
            return;
        }

        const currentChunkSize = Math.min(chunkSize, blobSize - offset);
        const chunk = blob.slice(offset, offset + currentChunkSize);

        const buffer = await new Promise<ArrayBuffer>((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (event) => {
                if (!event.target?.result) {
                    reject(new Error('读取文件块失败'));
                    return;
                }
                resolve(event.target.result as ArrayBuffer);
            };
            reader.onerror = () => {
                reject(new Error(`读取文件块错误：${reader.error?.message || '未知错误'}`));
            };
            reader.readAsArrayBuffer(chunk);
        });

        await onChunk(buffer, offset);
        offset += currentChunkSize;

        // 更新进度
        if (onProgress) {
            const progress = (offset / blobSize) * 100;
            onProgress(progress);
        }

        await readNextChunk();
    }

    await readNextChunk();
}
